// Size of a VM page on most host machines
#define PAGE_SIZE 4096

// Size of a byte
typedef uint8_t		phys_byte;

#ifdef MIPS64

	// Use 64 bit addresses
	typedef uint64_t	phys_addr;

	// In 64 bit mode the emulator allocates 16 host pages to
	// every emulator "page"
	#define MEM_PAGE (16*PAGE_SIZE)
	#define PAGE_MASK (MEM_PAGE-1)


	//  63       55  54            42  41              29
	// [X XXXX XXXX][X XXXX XXXX XXXX][X XXXX XXXX XXXX]
	//  PDPT    Page Directory    Page Table

	//  28            16  15                 0
	// [X XXXX XXXX XXXX][XXXX XXXX XXXX XXXX]
	//  Page              Offset

	typedef phys_byte	*****phys_mem;

	// Macro for sign extending 32 bit addresses
	#define EXT_ADDR(a)	((phys_addr)(int32_t)(a))

#else /* !MIPS64 */

	// Use 32 bit addresses
	typedef uint32_t	phys_addr;

	// In 32 bit mode an emulator "page" is the same size as a
	// host page
	#define PAGE_MASK 0x0FFF
	#define MEM_PAGE (HOST_PAGE_SIZE)

	//  32            22            12            0
	// [XX XXXX XXXX][XX XXXX XXXX][XXXX XXXX XXXX]
	//  Table         Page          Offset

	typedef phys_byte ***phys_mem;

	// 32 bit address clearly need no extension
	#define EXT_ADDR(a)	((phys_addr)(a))

#endif /* !MIPS64 */

/****
 * free_phys_memory - Free entire physical memory map
 * 
 * mem	- Memory map to free, must not be null
 *
 * Always returns E_OKAY
 **/
phys_error free_phys_memory(phys_mem mem);

/****
 * write_phys_memory - Writes data to a memory map
 *
 * mem		- Map to write to (mem != NULL)
 * addr		- Address to write at (need not be aligned)
 * bytes	- Number of bytes to write (must be a power of 2 < PAGE_SIZE)
 * v		- Data to write
 *
 * Returns E_OKAY on success, E_SYS_NOMEM if host memory could not be allocated
 **/
phys_error
write_phys_memory(	phys_mem mem,
					phys_addr addr,
					uint8_t bytes,
					const void *v);

/****
 * read_phys_memory - Reads data from a memory map
 *
 * mem		- Map to read from (mem != NULL)
 * addr		- Address to start read at (need not be aligned)
 * bytes	- Number of bytes to read (must be power of 2 < PAGE_SIZE)
 * v		- Buffer to read into
 *
 * Returns E_OKAY on success, if an address was not previously written
 * zero is always stored in the buffer.
 **/
phys_error
read_phys_memory(	phys_mem mem,
					phys_addr addr,
					uint8_t bytes,
					void *v);

